package com.zzedu.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zzedu.common.cache.CacheNameContansts;
import com.zzedu.common.core.domain.entity.SysUser;
import com.zzedu.common.enums.CommonEnums;
import com.zzedu.common.utils.StringUtils;
import com.zzedu.common.utils.bean.BeanUtils;
import com.zzedu.domain.*;
import com.zzedu.dto.ZzSchoolDTO;
import com.zzedu.enmuns.ConfigEnums;
import com.zzedu.framework.web.service.SysPasswordService;
import com.zzedu.mapper.*;
import com.zzedu.service.IZzAgentService;
import com.zzedu.service.IZzCourseService;
import com.zzedu.service.IZzSchoolCourseService;
import com.zzedu.service.IZzSchoolService;
import com.zzedu.system.domain.SysUserRole;
import com.zzedu.system.service.ISysConfigService;
import com.zzedu.system.service.ISysRegionService;
import com.zzedu.system.service.ISysUserRoleService;
import com.zzedu.system.service.ISysUserService;
import com.zzedu.vo.ZzSchoolReportVO;
import com.zzedu.vo.ZzSchoolVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 学校管理Service业务层处理
 *
 * @author Mr.Wang
 * @date 2025-01-27
 */
@Service
public class ZzSchoolServiceImpl extends ServiceImpl<ZzSchoolMapper, ZzSchool> implements IZzSchoolService {
    @Autowired
    IZzAgentService agentService;

    @Autowired
    ISysRegionService sysRegionService;
    @Autowired
    ISysUserService sysUserService;

    @Autowired
    SysPasswordService passwordService;
    @Autowired
    ISysUserRoleService sysUserRoleService;
    @Autowired
    ZzTeacherMapper zzTeacherMapper;
    @Autowired
    ZzStudentMapper zzStudentMapper;
    @Autowired
    ZzAppDeviceMapper zzAppDeviceMapper;

    @Autowired
    ZzClassesMapper zzClassesMapper;

    @Autowired
    IZzSchoolCourseService zzSchoolCourseService;

    @Autowired
    ZzCourseMapper zzCourseMapper;

    @Autowired
    IZzCourseService zzCourseService;

    @Autowired
    ISysConfigService sysConfigService;
    @Autowired
    ZzChargeOrderPayMapper zzChargeOrderPayMapper;
    @Autowired
    ZzChargeOrderMapper zzChargeOrderMapper;

    @Override
    public LambdaQueryWrapper<ZzSchool> buildQuery(ZzSchoolDTO zzSchool) {
        LambdaQueryWrapper<ZzSchool> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.like(StringUtils.isNotBlank(zzSchool.getSchoolName()), ZzSchool::getSchoolName, zzSchool.getSchoolName());
        lambdaQueryWrapper.like(StringUtils.isNotBlank(zzSchool.getSchoolAliaeName()), ZzSchool::getSchoolAliaeName, zzSchool.getSchoolAliaeName());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzSchool.getSchoolType()), ZzSchool::getSchoolType, zzSchool.getSchoolType());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzSchool.getLevelOfEducation()), ZzSchool::getLevelOfEducation, zzSchool.getLevelOfEducation());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzSchool.getTel()), ZzSchool::getTel, zzSchool.getTel());
        lambdaQueryWrapper.like(StringUtils.isNotBlank(zzSchool.getContacts()), ZzSchool::getContacts, zzSchool.getContacts());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzSchool.getIntroduce()), ZzSchool::getIntroduce, zzSchool.getIntroduce());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzSchool.getProvince()), ZzSchool::getProvince, zzSchool.getProvince());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzSchool.getCity()), ZzSchool::getCity, zzSchool.getCity());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzSchool.getDistrict()), ZzSchool::getDistrict, zzSchool.getDistrict());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzSchool.getAddress()), ZzSchool::getAddress, zzSchool.getAddress());
        lambdaQueryWrapper.eq(null != zzSchool.getState(), ZzSchool::getState, zzSchool.getState());
        lambdaQueryWrapper.eq(null != zzSchool.getPayState(), ZzSchool::getPayState, zzSchool.getPayState());
        if (CollectionUtils.isNotEmpty(zzSchool.getOrgIdArray())) {
            lambdaQueryWrapper.in(ZzSchool::getOrgId, zzSchool.getOrgIdArray());
        }
        if (CollectionUtils.isNotEmpty(zzSchool.getAgentIdArray())) {
            lambdaQueryWrapper.in(ZzSchool::getAgentId, zzSchool.getAgentIdArray());
        }
        List<String[]> queryProvinceAndCityAndDistrict = zzSchool.getQueryProvinceAndCityAndDistrict();
        if (CollectionUtils.isNotEmpty(queryProvinceAndCityAndDistrict)) {
            List<String> province = Lists.newArrayList();
            List<String> city = Lists.newArrayList();
            List<String> district = Lists.newArrayList();
            for (String[] provinceAndCityAndDistrict : queryProvinceAndCityAndDistrict) {
                if (null == provinceAndCityAndDistrict) {
                    continue;
                }
                if (StringUtils.isNotBlank(provinceAndCityAndDistrict[0])) {
                    province.add(provinceAndCityAndDistrict[0]);
                }
                if (provinceAndCityAndDistrict.length > 1 && StringUtils.isNotBlank(provinceAndCityAndDistrict[1])) {
                    city.add(provinceAndCityAndDistrict[1]);
                }
                if (provinceAndCityAndDistrict.length > 2 && StringUtils.isNotBlank(provinceAndCityAndDistrict[2])) {
                    district.add(provinceAndCityAndDistrict[2]);
                }
            }
            lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(province), ZzSchool::getProvince, province);
            lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(city), ZzSchool::getCity, city);
            lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(district), ZzSchool::getDistrict, district);
        }
        lambdaQueryWrapper.orderByDesc(ZzSchool::getId);
        return lambdaQueryWrapper;
    }

    @Override
    public List<ZzSchoolVO> convertVO(List<ZzSchool> zzSchoolList) {
        List<ZzSchoolVO> zzAgentVOList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(zzSchoolList)) {
            List<Long> agentIdList = zzSchoolList.stream().map(ZzSchool::getAgentId).collect(Collectors.toList());
            agentIdList.add(01L);
            List<ZzAgent> zzAgentList = agentService.listByIds(agentIdList);

            Map<Long, ZzAgent> zzAgentMap = Optional.ofNullable(zzAgentList).orElse(Lists.newArrayList())
                    .stream().collect(Collectors.toMap(ZzAgent::getId, Function.identity()));
            for (ZzSchool zzSchool : zzSchoolList) {
                ZzSchoolVO zzSchoolVO = new ZzSchoolVO();
                BeanUtils.copyBeanProp(zzSchoolVO, zzSchool);
                List<String> provinceAndCityAndDistrict = sysRegionService.provinceAndCityAndDistrict(Lists.newArrayList(zzSchool.getProvince(), zzSchool.getCity(), zzSchool.getDistrict()));
                if (CollectionUtils.isNotEmpty(provinceAndCityAndDistrict)) {
                    zzSchoolVO.setProvinceAndCityAndDistrict(Joiner.on("/").join(provinceAndCityAndDistrict));
                }
                if (null != zzSchool.getAgentId()) {
                    ZzAgent zzAgent = zzAgentMap.get(zzSchool.getAgentId());
                    if (null != zzAgent) {
                        zzSchoolVO.setAgentName(zzAgent.getAgentName());
                    }
                }
                zzSchoolVO.setSignArray(Lists.newArrayList());
                zzSchoolVO.setLevel(Lists.newArrayList());
                if (StringUtils.isNotBlank(zzSchool.getLevel())) {
                    zzSchoolVO.setLevel(JSON.parseArray(zzSchool.getLevel(), String.class));
                }
                if (null != zzSchool.getSignDate()) {
                    zzSchoolVO.getSignArray().add(zzSchool.getSignDate());
                }
                if (null != zzSchool.getSignDateEnd()) {
                    zzSchoolVO.getSignArray().add(zzSchool.getSignDateEnd());
                }
                zzAgentVOList.add(zzSchoolVO);
            }
        }
        return zzAgentVOList;
    }

    @Override
    public List<ZzSchoolReportVO> convertSchoolVO(List<ZzSchool> zzSchoolList) {
        List<ZzSchoolReportVO> schoolReportVOList = Lists.newArrayList();
        //实际招生人数
        if (CollectionUtils.isNotEmpty(zzSchoolList)) {
            List<Long> schoolIds = zzSchoolList.stream().map(ZzSchool::getId).collect(Collectors.toList());

            List<List<Long>> schoolIdLists = Lists.partition(schoolIds, 500);

            Map<Long, Integer> studentMap = Maps.newHashMap();
            Map<Long, Integer> teacherMap = Maps.newHashMap();
            Map<Long, Integer> deviceMap = Maps.newHashMap();
            Map<Long, Integer> clzzMap = Maps.newHashMap();
            for (List<Long> ids : schoolIdLists) {
                List<Map<String, Object>> value = zzStudentMapper.countStudentsBySchool(ids);
                if (CollectionUtils.isNotEmpty(value)) {
                    for (Map<String, Object> m : value) {
                        if (null != m.get("school_id")) {
                            studentMap.put(MapUtils.getLong(m, "school_id"), MapUtils.getIntValue(m, "student_count", 0));
                        }
                    }
                }
                List<Map<String, Object>> teacherValue = zzTeacherMapper.countTeachersBySchool(ids);
                if (CollectionUtils.isNotEmpty(teacherValue)) {
                    for (Map<String, Object> m : teacherValue) {
                        if (null != m.get("school_id")) {
                            teacherMap.put(MapUtils.getLong(m, "school_id"), MapUtils.getIntValue(m, "teacher_count", 0));
                        }
                    }
                }

                List<Map<String, Object>> deviceValue = zzAppDeviceMapper.countDevicesBySchool(ids);
                if (CollectionUtils.isNotEmpty(deviceValue)) {
                    for (Map<String, Object> m : deviceValue) {
                        if (null != m.get("school_id")) {
                            deviceMap.put(MapUtils.getLong(m, "school_id"), MapUtils.getIntValue(m, "device_count", 0));
                        }
                    }
                }
                List<Map<String, Object>> clzzValue = zzClassesMapper.countClzzsBySchool(ids);
                if (CollectionUtils.isNotEmpty(clzzValue)) {
                    for (Map<String, Object> m : clzzValue) {
                        if (null != m.get("school_id")) {
                            clzzMap.put(MapUtils.getLong(m, "school_id"), MapUtils.getIntValue(m, "clzz_count", 0));
                        }
                    }
                }

            }
            for (ZzSchool zzSchool : zzSchoolList) {
                ZzSchoolReportVO zzSchoolReportVO = new ZzSchoolReportVO();
                BeanUtils.copyBeanProp(zzSchoolReportVO, zzSchool);
                zzSchoolReportVO.setRealStudentCapacity(MapUtils.getIntValue(studentMap, zzSchool.getId(), 0));
                zzSchoolReportVO.setTeacherNum(MapUtils.getIntValue(teacherMap, zzSchool.getId(), 0));
                zzSchoolReportVO.setDeviceNum(MapUtils.getIntValue(deviceMap, zzSchool.getId(), 0));
                zzSchoolReportVO.setClzzNum(MapUtils.getIntValue(clzzMap, zzSchool.getId(), 0));
                schoolReportVOList.add(zzSchoolReportVO);
            }
        }
        return schoolReportVOList;
    }

    @Override
    @Transactional
    public boolean save(ZzSchoolDTO zzSchoolDTO) {
        ZzSchool zzSchool = new ZzSchool();
        BeanUtils.copyBeanProp(zzSchool, zzSchoolDTO);
        String[] provinceAndCityAndDistrict = zzSchoolDTO.getProvinceAndCityAndDistrict();
        if (null != provinceAndCityAndDistrict) {
            zzSchool.setProvince(provinceAndCityAndDistrict[0]);
            if (provinceAndCityAndDistrict.length > 1) {
                zzSchool.setCity(provinceAndCityAndDistrict[1]);
            }
            if (provinceAndCityAndDistrict.length > 2) {
                zzSchool.setDistrict(provinceAndCityAndDistrict[2]);
            }
        }
        if (CollectionUtils.isNotEmpty(zzSchoolDTO.getLevel())) {
            zzSchool.setLevel(JSON.toJSONString(zzSchoolDTO.getLevel()));
        }
        if (null != zzSchool.getOrgType()) {
            zzSchool.setBookCount(Integer.valueOf(zzSchool.getOrgType()));
        }
        zzSchool.setPayState(CommonEnums.NO.getCode());
        boolean res = super.save(zzSchool);
        //自动创建登录账号
        SysUser user = new SysUser();
        user.setNickName(zzSchool.getSchoolAliaeName());
        user.setUserName(zzSchool.getTel());
        user.setUserType(2);
        user.setStatus(CommonEnums.YES.getCode());
        user.setPassword("123456");
        user.setPassword(passwordService.encryptPassword(user.getPassword()));
        user.setUserTypeId(zzSchool.getId());
        this.sysUserService.save(user);
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setRoleId(104L);
        sysUserRole.setUserId(user.getId());
        sysUserRoleService.save(sysUserRole);

        //自动同步老师
        if (null == zzTeacherMapper.selectOne(Wrappers.lambdaQuery(ZzTeacher.class).eq(ZzTeacher::getTel, zzSchool.getTel()).last("limit 1"))) {
            ZzTeacher zzTeacher = new ZzTeacher();
            zzTeacher.setSchoolId(zzSchool.getId());
            zzTeacher.setPwd(passwordService.encryptPassword("123456"));
            zzTeacher.setTel(zzSchool.getTel());
            zzTeacher.setState(CommonEnums.YES.getCode());
            zzTeacher.setName(zzSchool.getSchoolAliaeName());
            zzTeacherMapper.insert(zzTeacher);
        }
        // 生成初始化解锁 学校unit 解锁课表
        List<String> levelList = zzSchoolDTO.getLevel();
        Integer unLimitCount = 2;
        if (null != zzSchool.getBookCount()) {
            unLimitCount = zzSchool.getBookCount();
        }
        for (String level : levelList) {
            // 按照级别 按照unit 序号 获取初始化unit
            List<ZzCourse> zzCourseList = zzCourseMapper.selectList(Wrappers.lambdaQuery(ZzCourse.class)
                    .eq(ZzCourse::getLevel, level)
                    .eq(ZzCourse::getState, CommonEnums.YES.getCode())
                    .orderByAsc(ZzCourse::getSortNo)
                    .orderByAsc(ZzCourse::getId)
                    .last("limit " + unLimitCount)
            );
            if (CollectionUtils.isNotEmpty(zzCourseList)) {
                for (ZzCourse course : zzCourseList) {
                    ZzSchoolCourse zzSchoolCourse = new ZzSchoolCourse();
                    zzSchoolCourse.setLevel(level);
                    zzSchoolCourse.setUnitId(course.getId());
                    zzSchoolCourse.setUnLockDate(LocalDateTime.now());
                    zzSchoolCourse.setSchoolId(zzSchool.getId());
                    zzSchoolCourseService.save(zzSchoolCourse);
                }
            }
        }
        return res;
    }

    @Override
    @Cacheable(value = CacheNameContansts.SCHOOL_CACHE, key = "'school:'+#p0")
    public ZzSchool getById(Serializable id) {
        return super.getById(id);
    }

    @Override
    @CacheEvict(value = CacheNameContansts.SCHOOL_CACHE, key = "'school:'+#p0.id")
    @Transactional(rollbackFor = Exception.class, readOnly = false)
    public boolean updateById(ZzSchoolDTO zzSchoolDTO) {

        ZzSchool dataBaseZzSchool = this.baseMapper.selectById(zzSchoolDTO.getId());
        ZzSchool zzSchool = new ZzSchool();
        BeanUtils.copyBeanProp(zzSchool, zzSchoolDTO);
        String[] provinceAndCityAndDistrict = zzSchoolDTO.getProvinceAndCityAndDistrict();
        if (null != provinceAndCityAndDistrict) {
            zzSchool.setProvince(provinceAndCityAndDistrict[0]);
            if (provinceAndCityAndDistrict.length > 1) {
                zzSchool.setCity(provinceAndCityAndDistrict[1]);
            }
            if (provinceAndCityAndDistrict.length > 2) {
                zzSchool.setDistrict(provinceAndCityAndDistrict[2]);
            }
        }
        if (CollectionUtils.isNotEmpty(zzSchoolDTO.getLevel())) {
            zzSchool.setLevel(JSON.toJSONString(zzSchoolDTO.getLevel()));
        }
        if (null != zzSchool.getOrgType()) {
            zzSchool.setBookCount(Integer.valueOf(zzSchool.getOrgType()));
        }
        List<String> levelList = JSON.parseArray(zzSchool.getLevel(), String.class);
        //增加# 需要 增加解锁
        for (String level : levelList) {
            //获取解锁
            List<ZzCourse> zzCourseList = zzCourseService.list(Wrappers.lambdaQuery(ZzCourse.class)
                    .eq(ZzCourse::getLevel, level)
                    .eq(ZzCourse::getState, CommonEnums.YES.getCode())
                    .notExists("select unit_id from zz_school_course where deleted=0 and school_id={0} and level={1} and unit_id=zz_course.id", zzSchool.getId(), level)
                    .le(ZzCourse::getSortNo, zzSchool.getBookCount())
                    .orderByAsc(ZzCourse::getSortNo)
                    .orderByAsc(ZzCourse::getId)
            );
            for (ZzCourse zzCourse : zzCourseList) {
                ZzSchoolCourse zzSchoolCourse = new ZzSchoolCourse();
                zzSchoolCourse.setLevel(level);
                zzSchoolCourse.setUnitId(zzCourse.getId());
                zzSchoolCourse.setUnLockDate(LocalDateTime.of(LocalDate.now().withDayOfMonth(1), LocalTime.MIN));
                zzSchoolCourse.setSchoolId(zzSchool.getId());
                if (null == zzSchoolCourseService.getOne(Wrappers.lambdaQuery(ZzSchoolCourse.class)
                        .eq(ZzSchoolCourse::getSchoolId, zzSchool.getId())
                        .eq(ZzSchoolCourse::getUnitId, zzCourse.getId())
                        .last("limit 1 ")
                )) {
                    zzSchoolCourseService.save(zzSchoolCourse);
                }
            }
        }

        return super.updateById(zzSchool);
    }

    @Override
    public boolean isTestSchoolFlag(Long id) {
        String ids = sysConfigService.selectConfigByKeyCache(ConfigEnums.SYS_TEST_SCHOOL_CONFIG.getCode());
        return ("," + ids + ",").contains("," + id + ",");
    }

    @Override
    @CacheEvict(value = CacheNameContansts.SCHOOL_CACHE, key = "'school:'+#p0")
    public void refreshCache(Long id) {

    }

    @Override
    @CacheEvict(value = CacheNameContansts.SCHOOL_CACHE, allEntries = true)
    public void refreshCacheAll() {

    }

}